/*
ID: majowi1
LANG: JAVA
PROG: milk2
*/

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;

final class milk2 {
	
	public static void main(String[] args) throws IOException {
		BufferedReader f = new BufferedReader(new FileReader("milk2.in"));	    
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("milk2.out")));
		StringTokenizer st;
		int i1,i2, farmers;
		int x,x2,x3;
		int[] cmon = new int[1], cmon2;	    
		farmers = Integer.parseInt(f.readLine());	    
		for (x = 1; x <= farmers ; x++){
			st = new StringTokenizer(f.readLine());  	
			i1 = Integer.parseInt(st.nextToken());
			i2 = Integer.parseInt(st.nextToken());
			
			if (cmon.length < i2){
				cmon2 = new int[i2]; // WE need 2 spots ekstra because the minutes should be the containers, and not the seperators in the array
				System.arraycopy(cmon, 0, cmon2, 0, 
		                Math.min(cmon.length, cmon2.length));
				cmon = cmon2;	    	
			}
			
			//farmer 
			//correctly build should not include count in last position (
			//meaning if area is ex 3-12 arraypositions should be filled 2-10
			
			for(x2=i1;x2<i2;x2++){ 
				if (cmon[x2] == 0)
					cmon[x2] = x;
				else
					cmon[x2] = farmers+1;
			}
		}


		// count the longest milkingtime and the longest idletime
		// there must be a milkingtime before an idletime
		// if the change between the previous index and the current is farmers+1 its overlaptime
		//
		// 

		int lastcount = 0, milkrecord = 0, idlerecord = 0, previous = 0;
		boolean theend;
		for (x3=0; x3<cmon.length;x3++){
			
			theend = (x3 == cmon.length-1);
			
			//is theres a change and its not overlap, or its the end- count the record
			 
			if ((cmon[x3] != previous && 	// Theres been a change
				cmon[x3] != farmers+1 &&	// Current is not overlap
				(!(cmon[x3-1] > 0 && cmon[x3] > 0)) && // two next to eachother > 0 is also overlap
				previous != farmers+1) ||	// Previous is not overlap OR
				theend){ 					// Its the last
				int _cmonx3 = cmon[x3];
				//if its the end AND its either the same as previous OR previous = farmers+1 OR current = farmers+1 
				//it must be countet as milkingtime (+1 for arraycontrol) - execute and break loop.
				if(theend && cmon[x3] == previous || cmon[x3] == farmers+1 || previous == farmers+1){
					if (milkrecord < (x3+1)-lastcount)
					milkrecord = (x3+1)-lastcount;
					break;	    			
				}
				
				//if (!(cmon[x3-1] > 0 && cmon[x3] > 0))
				
				//tjeck idletime - only if it changes from zero and the record is beat (+there must be a milkingtime before an idletime)
				if (cmon[x3] > 0 && milkrecord > 0 && idlerecord < (x3)-lastcount)
					idlerecord = (x3)-lastcount;
				
				
				//tjeck milkingtime - only if it changes to zero and the record is beat
				if (cmon[x3] == 0 && milkrecord < (x3)-lastcount)
					milkrecord = (x3)-lastcount;
				
				lastcount = x3;
			}
			previous = cmon[x3];
		}


		out.println(milkrecord + " " + idlerecord);
		out.close();
		System.exit(0);
		}
		}
	
	/*
	public static void main(String[] args) throws IOException {
		BufferedReader f = new BufferedReader(new FileReader("milk2.in"));	    
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("milk2.out")));
		StringTokenizer st;
		int low,high,farmers;
		farmers = Integer.parseInt(f.readLine());
		
		Milkrec m = new Milkrec();
		
		for (int x = 1; x <= farmers ; x++){
			st = new StringTokenizer(f.readLine());  	
			low = Integer.parseInt(st.nextToken());
			high = Integer.parseInt(st.nextToken());
			
			m.tjeckMilk(high,low);
		}
		System.out.println(m.printResult());
		out.println(m.printResult());
		out.close();
		System.exit(0);
	}
	
	private static class Milkrec{
		int max=0,min=0,idle=0;		
		public void tjeckMilk(int p_max, int p_min){
			int _max = max, _min = min, _idle = idle;
			
			  if (!isBetween(p_max,p_min))
				if (!isBigger(p_max,p_min))
					idleTjeck(p_max,p_min);
		}
		
		public String printResult(){			
			return (max-min)+" "+idle;
		}
		
		private boolean isBetween(int p_max, int p_min){					
			if (p_max >= min && p_max <= max){
				if (p_min < min){
					min = p_min;
					return true;
				}
			}
			if	(p_min >= min && p_min <= max){
				if (p_max > max){
					max = p_max;
					return true;
				}
			}
			return false;
		}
		
		private boolean isBigger(int p_max, int p_min){			
			if (p_max - p_min > max-min){
				max = p_max;
				min = p_min;
				return true;
			}
			return false;
		}
		
		private void idleTjeck(int p_max, int p_min){
			if (p_max < min){
				if(min - p_max > idle){
					idle = min-p_max;
					return;
				}
			}
			if (p_min > max){
				if (p_min - max > idle){
					idle = p_min - max;		
				}
			}	
		}
	}
}
	
	*/

